package com.bang.daybreak.common.config;

import com.bang.daybreak.common.annotation.TargetDataSource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import java.lang.reflect.Method;

/**
 * @author : wdj
 * @since : 2019/1/6 0006 下午 15:45
 * @version 1.0
 */
@Component
@Aspect
@Slf4j
//由于引入多数据源，所以让spring事务的aop要在多数据源切换aop的后面
@EnableTransactionManagement(order = 0)
public class DataSourceAspect implements Ordered {

    /**
     * 切换放在mapper接口的方法上，所以这里要配置AOP切面的切入点
     */
//    @Pointcut("execution( * com.bang.tjfile.*.mapper.*.*(..))")
    @Pointcut(value = "@annotation(com.bang.daybreak.common.annotation.TargetDataSource)")
    public void dataSourcePointCut() {
    }

    @Before("dataSourcePointCut()")
    public void before(JoinPoint point) throws NoSuchMethodException {
/*        Object target = joinPoint.getTarget();
        String method = joinPoint.getSignature().getName();
        Class<?>[] clazz = target.getClass().getInterfaces();
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        try {
            Method m = clazz[0].getMethod(method, parameterTypes);
            //如果方法上存在切换数据源的注解，则根据注解内容进行数据源切换
            if (m != null && m.isAnnotationPresent(TargetDataSource.class)) {
                TargetDataSource data = m.getAnnotation(TargetDataSource.class);
                String dataSourceName = data.value();
                DynamicDataSourceHolder.putDataSource(dataSourceName);
                log.debug("current thread " + Thread.currentThread().getName() + " add " + dataSourceName + " to ThreadLocal");
            } else {
                log.debug("switch datasource fail,use default");
            }
        } catch (Exception e) {
            log.error("current thread " + Thread.currentThread().getName() + " add data to ThreadLocal error", e);
        }*/

      /*
        注解在类上
      Class<?> className = point.getTarget().getClass();
        if (className.isAnnotationPresent(TargetDataSource.class)) {
            TargetDataSource annotation = className.getAnnotation(TargetDataSource.class);
            String value = annotation.value();
            if (value != null && value!="") {
                DynamicDataSourceHolder.putDataSource(value);
            }
        } else {
            System.out.println(className);
        }*/

        Signature signature = point.getSignature();
        // 需要获取到的是实现类中的具体方法.
        MethodSignature methodSignature = null;
        if (!(signature instanceof MethodSignature)) {
            throw new IllegalArgumentException("该注解只能用于方法");
        }
        methodSignature = (MethodSignature) signature;
        Object target = point.getTarget();
        Method currentMethod = target.getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        TargetDataSource dynamicSource = currentMethod.getAnnotation(TargetDataSource.class);
        DynamicDataSourceHolder.putDataSource(dynamicSource.value());

    }

    /**
     * aop的顺序要早于spring的事务
     */
    @Override
    public int getOrder() {
        return 1;
    }

    /**
     * 执行完切面后，将线程共享中的数据源名称清空
     *
     * @param joinPoint
     */
    @After("dataSourcePointCut()")
    public void after(JoinPoint joinPoint) {
        DynamicDataSourceHolder.removeDataSource();
    }
}
